/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package semantico;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;

/**
 *
 * @author gabriel
 */
public class Declaracao implements Cloneable, Serializable {

    private String escopo; //local | global
    private String categoria; //local: var, const, registro | global: funcao, procedimento
    private String identificador;
    private String tipo; // inteiro, literal, etc
    private boolean ptr;
    private boolean array;
    private String valor; //local: conteudo | global: retorno funcao ou void
    private ArrayList<Declaracao> dimensao; //local
    private ArrayList<Declaracao> parametro; //global | array  
    private ArrayList<Declaracao> decLocais; //global
    private int linha;
    private boolean erro;
    public static final int ERRO_SEMANTICO_1 = 1;
    public static final int ERRO_SEMANTICO_2 = 2;
    public static final int ERRO_SEMANTICO_3 = 3;
    public static final int ERRO_SEMANTICO_4 = 4;
    public static final int ERRO_SEMANTICO_5 = 5;
    public static final int ERRO_SEMANTICO_6 = 6;

    public Declaracao() {
        this.escopo = "";
        this.categoria = "";
        this.identificador = "";
        this.tipo = "";
        this.valor = "";
        this.decLocais = new ArrayList<Declaracao>();
        this.dimensao = new ArrayList<Declaracao>();
        this.parametro = new ArrayList<Declaracao>();
    }

    public Declaracao(String escopo, String categoria, String identificador, String tipo, boolean ptr, boolean array) {
        this.escopo = escopo;
        this.categoria = categoria;
        this.identificador = identificador;
        this.tipo = tipo;
        this.ptr = ptr;
        this.array = array;
        this.decLocais = new ArrayList<Declaracao>();
        this.dimensao = new ArrayList<Declaracao>();
        this.parametro = new ArrayList<Declaracao>();
        this.valor = "";
    }

    public Declaracao(String escopo, String categoria, String identificador, String tipo, boolean ptr, boolean array, String valor, ArrayList<Declaracao> dimensao, ArrayList<Declaracao> parametro, ArrayList<Declaracao> decLocais, int linha, boolean erro) {
        this.escopo = escopo;
        this.categoria = categoria;
        this.identificador = identificador;
        this.tipo = tipo;
        this.ptr = ptr;
        this.array = array;
        this.valor = valor;
        this.dimensao = dimensao;
        this.parametro = parametro;
        this.decLocais = decLocais;
        this.linha = linha;
        this.erro = erro;
    }

    public String getCategoria() {
        return categoria;
    }

    public void setCategoria(String categoria) {
        this.categoria = categoria;
    }

    public String getEscopo() {
        return escopo;
    }

    public void setEscopo(String escopo) {
        this.escopo = escopo;
    }

    public boolean isArray() {
        return array;
    }

    public void setArray(boolean array) {
        this.array = array;
    }

    public ArrayList<Declaracao> getDimensao() {
        return dimensao;
    }

    public void setDimensao(ArrayList<Declaracao> dimensao) {
        this.dimensao = dimensao;
    }

    public String getIdentificador() {
        return identificador;
    }

    public void setIdentificador(String identificador) {
        this.identificador = identificador;
    }

    public int getLinha() {
        return linha;
    }

    public void setLinha(int linha) {
        this.linha = linha;
    }

    public boolean isPtr() {
        return ptr;
    }

    public void setPtr(boolean ptr) {
        this.ptr = ptr;
    }

    public String getTipo() {
        return tipo;
    }

    public void setTipo(String tipo) {
        this.tipo = tipo;
    }

    public String getValor() {
        return valor;
    }

    public void setValor(String valor) {
        this.valor = valor;
    }

    public ArrayList<Declaracao> getParametro() {
        return parametro;
    }

    public void setParametro(ArrayList<Declaracao> parametro) {
        this.parametro = parametro;
    }

    public ArrayList<Declaracao> getDecLocais() {
        return decLocais;
    }

    public void setDecLocais(ArrayList<Declaracao> decLocais) {
        this.decLocais = decLocais;
    }

    public boolean isErro() {
        return erro;
    }

    public void setErro(boolean erro) {
        this.erro = erro;
    }

    @Override
    public boolean equals(Object o) {
        if (this.getClass().equals(o.getClass())) {
            if (this.hashCode() == o.hashCode()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return (this.identificador != null ? (this.identificador + this.escopo).hashCode() : 0);
    }

    @Override
    public Declaracao clone() {
        /* Declaracao tmp = new Declaracao();
        tmp.array = this.array;
        tmp.categoria = this.categoria;
        tmp.dimensao = this.dimensao;
        tmp.decLocais = this.decLocais;
        tmp.escopo = this.escopo;
        tmp.identificador = this.identificador;
        tmp.linha = this.linha;
        tmp.parametro = this.parametro;
        tmp.ptr = this.ptr;
        tmp.tipo = this.tipo;
        tmp.valor = this.valor;
        tmp.erro = this.erro;
        return tmp;
         */
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(this);
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            Object deepCopy = ois.readObject();
            return (Declaracao) deepCopy;
        } catch (Exception e) {
            return this;
        }
    }
}
